package cn.aitrox.ry.service.oss.controller;

import cn.aitrox.ry.bean.RespResult;
import cn.aitrox.ry.service.oss.api.OssFileApi;
import cn.aitrox.ry.service.oss.config.OssNacosProperties;
import cn.aitrox.ry.service.oss.dto.FileRestoreInfoDto;
import cn.aitrox.ry.service.oss.dto.in.DowanloadUrlGetInDto;
import cn.aitrox.ry.service.oss.interceptor.OssKeyThreadLocal;
import cn.aitrox.ry.service.oss.service.OssFileService;
import cn.aitrox.ry.util.LogUtil;
import cn.aitrox.ry.util.MimeTypeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

@RestController
public class OssFileController implements OssFileApi {

    private static final Logger LOG = LoggerFactory.getLogger(OssFileController.class);

    @Autowired
    private OssFileService ossFileService;

    @Autowired
    private OssKeyThreadLocal ossKeyThreadLocal;

    @Autowired
    private OssNacosProperties ossNacosProperties;

    @PostMapping(value = "/oss/file/url/get")
    @Override
    public RespResult<List<FileRestoreInfoDto>> urlGet(DowanloadUrlGetInDto input) {
        try {
            List<FileRestoreInfoDto> fileRestoreInfos = ossFileService.urlGet(input.getResourceKeys(), input.getExpireSeconds(), input.getOssType());
            return RespResult.ok(fileRestoreInfos);
        } catch (Exception e) {
            return RespResult.error(e.getMessage());
        }
    }

    @PostMapping(value = "/oss/file/put")
    @Override
    public RespResult put(@RequestParam("key") String key, @RequestPart("file") MultipartFile mfile, @RequestParam("ossType") String ossType) {
        try {
            return ossFileService.put(key, mfile.getInputStream(), mfile.getOriginalFilename(), ossType);
        } catch (Exception e) {
            return RespResult.error(e.getMessage());
        }
    }

    @Override
    public @PostMapping(value = "/oss/file/put/local")
    RespResult putLocal(@RequestParam("key") String key, @RequestParam("filePath") String filePath, @RequestParam("ossType") String ossType) {
        try {
            return ossFileService.putLocal(key, filePath, ossType);
        } catch (Exception e) {
            return RespResult.error(e.getMessage());
        }
    }

    @DeleteMapping(value = "/oss/file/delete")
    @Override
    public RespResult delete(@RequestParam("key") String key, @RequestParam("ossType") String ossType) {
        try {
            return ossFileService.delete(key, ossType);
        } catch (Exception e) {
            return RespResult.error(e.getMessage());
        }
    }

    @PostMapping(value = "/oss/file/copy")
    @Override
    public RespResult copy(@RequestParam("sourceKey") String sourceKey, @RequestParam("targetKey") String targetKey, @RequestParam("ossType") String ossType) {
        try {
            return ossFileService.copy(sourceKey, targetKey, ossType);
        } catch (Exception e) {
            return RespResult.error(e.getMessage());
        }
    }

    @PostMapping(value = "/oss/file/move")
    @Override
    public RespResult move(@RequestParam("filePath") String filePath, @RequestParam("key") String key, @RequestParam("ossType") String ossType) {
        try {
            return ossFileService.move(filePath, key, ossType);
        } catch (Exception e) {
            return RespResult.error(e.getMessage());
        }
    }

    @Override
    @RequestMapping("/oss/file/download/**")
    public void download(HttpServletResponse response) throws IOException {
        String ossKey = ossKeyThreadLocal.getOssKey();

        // 判断文件是否存在
        File file = new File(ossNacosProperties.getPrePath(), ossKey);
        if (!file.exists()) {
            response.setStatus(HttpStatus.NOT_FOUND.value());
            response.getWriter().write(HttpStatus.NOT_FOUND.getReasonPhrase());
            return;
        }

        String mimeType = MimeTypeUtil.APPLICATION_OCTET_STREAM;
        try {
            mimeType = MimeTypeUtil.getMimeType(file);
        } catch (Exception e) {
            LOG.error(LogUtil.gen("获取媒体类型失败", "ossKey", ossKey), e);
        }

        long start = System.currentTimeMillis();
        LOG.info(LogUtil.gen("下载开始", "key", ossKey));

        FileInputStream is = null;
        long contentLength = 0;
        OutputStream os = null;
        int len;
        byte[] buffer = new byte[8192];
        try {
            is = new FileInputStream(file);
            os = response.getOutputStream();
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
                contentLength += len;
            }
            response.setContentLengthLong(contentLength);
            response.setContentType(mimeType);
        } finally {
            LOG.info(LogUtil.gen("下载结束", "cost", (System.currentTimeMillis() - start) + "", "key", ossKey));
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                }
            }
        }
    }
}
